

/**
 * The surface editing dialog
 * @author Narendra J. Mondal
 * @date 15.01.2012
 */

package plotter;



import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

class EditDialog extends JDialog
{
	// settings for plotting surface
	private PlotSettings ps;
	
	// the rendering panel
	private PlotPanel ppanel;
	
	JTabbedPane tp = new JTabbedPane();
	
	// whether the equation is parametric
	JCheckBox cbIsParam = new JCheckBox("Equation is Parametric");
	
	// the three equation labels and fields
	JLabel el1 = new JLabel("x = f(u, v) = ");
	JTextField ef1 = new JTextField(30);
	
	JLabel el2 = new JLabel("y = g(u, v) = ");
	JTextField ef2 = new JTextField(30);
	
	JLabel el3 = new JLabel("z = h(u, v) = ");
	JTextField ef3 = new JTextField(30);
	
	// the range fields
	JTextField xmin = new JTextField(10);
	JLabel xl = new JLabel("u");
	JTextField xmax = new JTextField(10);
	
	JTextField ymin = new JTextField(10);
	JLabel yl = new JLabel("v");
	JTextField ymax = new JTextField(10);
	
	// whether to fill surface
	JCheckBox cbFill=new JCheckBox("Fill Surface");
	//JCheckBox cbAxes=new JCheckBox("Draw Axes");
	
	// colour 'chooser' buttons; see ColorButton class
	ColorButton btnBkColor, btnGridColor, btnSurface1, btnSurface2;
	
	// plot and cancel buttons
	JButton plot = new JButton("Plot");
	JButton cancel = new JButton("Cancel");
	
	// action class to be used when check-boxes are selected
	CheckAction chka = new CheckAction();
	
	public EditDialog(JFrame parent, PlotPanel pp) 
	{
		// it is a modeless dialog box
		super(parent, "Edit Surface", false);
		ppanel = pp;
		this.ps=pp.getPlotSettings();
		
		// do not exit on hitting close button
		setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
		
		// size is fixed
		setResizable(false);
		
		btnBkColor = new ColorButton(ps.bkcolor);
		btnGridColor = new ColorButton(ps.gridcolor);
		btnSurface1 = new ColorButton(ps.surface1);
		btnSurface2 = new ColorButton(ps.surface2);
		
		tp.add("Equation", createEqnPanel());
		tp.add("Drawing Options", createDrawingPanel());
		add(tp, BorderLayout.NORTH);
		
		BtnAction ba = new BtnAction();
		Box b = Box.createHorizontalBox();
		b.add(Box.createHorizontalGlue());
		plot.addActionListener(ba);
		b.add(plot);
		b.add(Box.createHorizontalStrut(10));
		cancel.addActionListener(ba);
		b.add(cancel);
		
		add(b, BorderLayout.SOUTH);
		pack();
	}
	private JPanel createEqnPanel()
	{
		JPanel p = new JPanel();
		
		Box b = Box.createVerticalBox();
		cbIsParam.setSelected(ps.isparametric);
		cbIsParam.addActionListener(chka);
		b.add(cbIsParam);
		b.add(Box.createVerticalStrut(10));
		
		Box b1 = Box.createHorizontalBox();
		b1.add(el1);
		b1.add(Box.createHorizontalStrut(10));
		ef1.setText(ps.eqn1);
		b1.add(ef1);
		b.add(b1);
		b.add(Box.createVerticalStrut(10));
		
		Box b2 = Box.createHorizontalBox();
		b2.add(el2);
		b2.add(Box.createHorizontalStrut(10));
		ef2.setText(ps.eqn2);
		b2.add(ef2);
		b.add(b2);
		b.add(Box.createVerticalStrut(10));
		
		Box b3 = Box.createHorizontalBox();
		b3.add(el3);
		b3.add(Box.createHorizontalStrut(10));
		ef3.setText(ps.eqn3);
		b3.add(ef3);
		b.add(b3);
		b.add(Box.createVerticalStrut(10));
		
		
		// the equation range panel
		JPanel rp = new JPanel();
		rp.setBorder(BorderFactory.createTitledBorder("Ranges"));
		Box b4 = Box.createVerticalBox();
		
		Box b5 = Box.createHorizontalBox();
		b5.add(xmin);
		b5.add(Box.createHorizontalStrut(20));
		b5.add(xl);
		b5.add(Box.createHorizontalStrut(20));
		b5.add(xmax);
		b4.add(b5);
		b4.add(Box.createVerticalStrut(10));
		
		Box b6 = Box.createHorizontalBox();
		b6.add(ymin);
		b6.add(Box.createHorizontalStrut(20));
		b6.add(yl);
		b6.add(Box.createHorizontalStrut(20));
		b6.add(ymax);
		b4.add(b6);
		rp.add(b4);
		
		b.add(rp);
		
		p.add(b);
		
		enableFields();
		
		return p;
	}
	private JPanel createDrawingPanel()
	{
		JPanel p = new JPanel();
		
		Box b = Box.createVerticalBox();
		
		
		
		Box b1 = Box.createHorizontalBox();
		cbFill.setSelected(ps.fillsurface);
		cbFill.addActionListener(chka);
		b1.add(cbFill);
		b1.add(Box.createHorizontalStrut(10));
		//cbAxes.setSelected(ps.drawaxes);
		//cbAxes.addActionListener(chka);
		//b1.add(cbAxes);
		b.add(b1);
		b.add(Box.createVerticalStrut(30));
		
		// the colour panel where the 'chooser' buttons are palced 
		JPanel cp = new JPanel();
		cp.setLayout(new GridLayout(4, 2, 5, 5));
		
		ColorAction ca = new ColorAction();
		cp.add(new JLabel("Back Color:"));
		btnBkColor.addActionListener(ca);
		cp.add(btnBkColor);
		cp.add(new JLabel("Grid Color:"));
		btnGridColor.addActionListener(ca);
		cp.add(btnGridColor);
		cp.add(new JLabel("First Surface:"));
		btnSurface1.addActionListener(ca);
		cp.add(btnSurface1);
		cp.add(new JLabel("Second Surface:"));
		btnSurface2.addActionListener(ca);
		cp.add(btnSurface2);
		b.add(cp);
		
		p.add(b);
		
		return p;
	}
	/**
	 * enable or disable components according as the eqn is parametric or cartesian
	 * also, change the dummy variable names x,y to u,v
	 */
	public void enableFields()
	{
		if (ps.isparametric) {
			el1.setText("x = f(u, v) = ");
			el2.setEnabled(true);
			ef2.setEnabled(true);
			el3.setEnabled(true);
			ef3.setEnabled(true);
			
			xl.setText("u");
			yl.setText("v");
			
		}
		else {
			el1.setText("z = f(x, y) = ");
			el2.setEnabled(false);
			ef2.setEnabled(false);
			el3.setEnabled(false);
			ef3.setEnabled(false);
			
			xl.setText("x");
			yl.setText("y");
		}
		xmin.setText(String.format("%f", ps.xmin));
		xmax.setText(String.format("%f", ps.xmax));
		
		ymin.setText(String.format("%f", ps.ymin));
		ymax.setText(String.format("%f", ps.ymax));
	}
	/**
	 * Utility function for converting a string to a double
	 * @param s the input string
	 * @return the double value of string
	 */
	public double strToDouble(String s) 
	{
		s.replace('+', ' ');
		return Double.parseDouble(s.trim());
	}
	private class BtnAction extends AbstractAction
	{
		public void actionPerformed(ActionEvent e) {
			JButton b = (JButton)e.getSource();
			
			
			if (b.equals(plot)) {
				ps.eqn1 = ef1.getText()+"\n";
				if (ps.isparametric) {
					ps.eqn2 = ef2.getText()+"\n";
					ps.eqn3 = ef3.getText()+"\n";
				}
				else {
					//ps.eqn1=ef1.getText();
					ps.eqn2 = ps.eqn3 = null;
				}
				try {
					// throws NumberFormatException if range fields contain something other than number
					ps.xmin = strToDouble(xmin.getText());
					ps.xmax = strToDouble(xmax.getText());
					ps.ymin = strToDouble(ymin.getText());
					ps.ymax = strToDouble(ymax.getText());
				}
				catch (Exception ex) {
					JOptionPane.showMessageDialog(EditDialog.this, "Only numbers are allowed as range", "SurfPlot", JOptionPane.ERROR_MESSAGE);
					return;
				}
				// set this settings as plot settings and replot
				ppanel.updateSettings(ps);
			}
			// hide dialog if 'Cancel' is pressed
			else if (b.equals(cancel)) setVisible(false);
		}
	}
	private class CheckAction extends AbstractAction
	{
		public void actionPerformed(ActionEvent e) {
			JCheckBox cb = (JCheckBox)e.getSource();
			boolean sel = cb.isSelected();
			
			if (cb.equals(cbIsParam)) {
				ps.isparametric = sel;
				enableFields();
			}
			else if (cb.equals(cbFill)) ps.fillsurface = sel;
			//else if (cb.equals(cbAxes)) ps.drawaxes = sel;
			//ppanel.updateSettings(ps);
		}
	}
	/**
	 * Used when one of the colour buttons is selected 
	 * @author Narendra J. Mondal
	 *
	 */
	private class ColorAction extends AbstractAction
	{
		public void actionPerformed(ActionEvent e) {
			ColorButton cb = (ColorButton)e.getSource();
			Color c = cb.getChosenColor();
			
			if (c == null) return;
			if (cb.equals(btnBkColor)) ps.bkcolor = c;
			else if (cb.equals(btnGridColor)) ps.gridcolor = c;
			//else if (cb.equals(netc)) ps.netColor=c;
			else if (cb.equals(btnSurface1)) ps.surface1 = c;
			else ps.surface2 = c;
			//ppanel.updateSettings(ps);
			
		}
	}
}
